<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>六足机器人上位机</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.155.0/examples/js/controls/OrbitControls.js"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36D399',
                        accent: '#FF6B35',
                        dark: '#1E293B',
                        light: '#F8FAFC',
                        frame: '#E2E8F0',
                        control: '#FF5722',
                        radar: '#00FF00',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .grid-layout {
                grid-template-rows: 65% 35%;
                height: 100%;
            }
            .grid-layout-right {
                grid-template-rows: 50% 50%;
                height: 100%;
            }
            .frame-border {
                border: 5px solid theme('colors.frame');
            }
            .app-height {
                height: calc(100vh);
            }
            .key-button {
                @apply w-12 h-12 flex items-center justify-center rounded-lg bg-gray-100 text-gray-700 font-medium transition-all duration-200 shadow-sm;
            }
            .key-button-active {
                @apply bg-control text-white transform scale-105 shadow-md;
            }
            .robot-arena {
                @apply relative w-full h-full bg-gray-100 rounded-lg overflow-hidden;
            }
            .robot {
                @apply absolute w-12 h-12 bg-control rounded-full flex items-center justify-center text-white transition-all duration-150 shadow-md;
            }
            .keyboard-container {
                @apply grid grid-cols-3 gap-2 justify-center max-w-[12rem] mx-auto;
            }
            .video-container {
                @apply relative w-full h-full bg-gray-100 rounded-lg overflow-hidden;
            }
            .video-placeholder {
                @apply absolute inset-0 flex flex-col items-center justify-center bg-gray-100;
            }
            .robot-visualization {
                @apply w-full h-full bg-gray-50 rounded-lg overflow-hidden;
            }
            .radar-container {
                @apply w-full h-full bg-dark rounded-lg overflow-hidden relative;
            }
            .radar-controls {
                @apply absolute top-2 right-2 flex gap-1 z-10;
            }
            .radar-control-btn {
                @apply bg-white/20 hover:bg-white/40 text-white p-1 rounded text-xs transition-colors;
            }
        }
    </style>
</head>
<body class="font-inter bg-gray-50">
    <!-- 主要内容区 -->
    <div class="relative app-height frame-border overflow-hidden w-full max-w-7xl mx-auto">
        <!-- 左右分隔线 -->
        <div class="absolute left-1/2 top-0 bottom-0 w-[5px] bg-frame -ml-[2.5px] z-10"></div>

        <!-- 左侧区域 -->
        <div class="absolute left-0 top-0 bottom-0 w-1/2 grid grid-layout">
            <!-- 左侧上下分隔线 -->
            <div class="absolute left-0 right-0 top-[65%] h-[5px] bg-frame -mt-[2.5px] z-10"></div>

            <!-- 左上区域 - ESP32-CAM视频显示 -->
            <div class="bg-white p-4 overflow-hidden relative">
                <div class="absolute inset-0 bg-primary/5 z-0"></div>
                <div class="relative z-10">
                    <h2 class="text-xl font-bold text-dark mb-3 flex items-center">
                        <i class="fa fa-area-chart text-primary mr-2"></i>
                        摄像头
                    </h2>

                    <!-- 视频显示区域 -->
                    <div class="video-container">
                        <!-- 视频占位符，视频加载时显示 -->
                        <div id="video-placeholder" class="video-placeholder">
                            <div class="animate-pulse rounded-full h-16 w-16 bg-gray-300 mb-3"></div>
                            <div class="animate-pulse rounded h-3 w-3/4 bg-gray-300 mb-2"></div>
                            <div class="animate-pulse rounded h-3 w-1/2 bg-gray-300"></div>
                            <p class="mt-4 text-gray-500 text-sm">正在连接ESP32-CAM...</p>
                        </div>

                        <!-- 视频元素 -->
                        <img id="esp32-cam-video" src="https://picsum.photos/800/600" alt="ESP32-CAM视频流" class="w-full h-full object-cover hidden">

                        <!-- 视频控制按钮 -->
                        <div class="absolute bottom-3 right-3 flex gap-2 z-20">
                            <button id="refresh-video" class="bg-white/80 hover:bg-white text-primary p-2 rounded-full shadow-md transition-colors">
                                <i class="fa fa-refresh"></i>
                            </button>
                            <button id="fullscreen-video" class="bg-white/80 hover:bg-white text-primary p-2 rounded-full shadow-md transition-colors">
                                <i class="fa fa-expand"></i>
                            </button>
                        </div>
                    </div>

                    <!-- 视频状态信息 -->
                    <div class="mt-2 flex justify-between items-center">
                        <div class="text-xs text-gray-500">
                            <span id="video-status">状态: 已连接</span>
                        </div>
                    </div>
                </div>
                <div class="absolute -bottom-3 -right-3 w-16 h-16 bg-primary/10 rounded-full"></div>
            </div>

            <!-- 左下区域 - 机器人控制 -->
            <div class="bg-white p-4 overflow-hidden relative">
                <div class="absolute inset-0 bg-control/5 z-0"></div>
                <div class="relative z-10">
                    <h2 class="text-lg font-bold text-dark mb-2 flex items-center">
                        <i class="fa fa-gamepad text-control mr-2"></i>
                        机器人控制
                    </h2>

                    <!-- 步态切换按钮区域 -->
                    <div class="absolute top-4 right-4 flex gap-2 z-20">
                        <button id="gait-wave" class="px-2 py-1 rounded-md text-xs transition-all duration-200 bg-gray-200 text-gray-700 hover:bg-gray-300">
                            Wave
                        </button>
                        <button id="gait-triangle" class="px-2 py-1 rounded-md text-xs transition-all duration-200 bg-control text-white">
                            Triangle
                        </button>
                    </div>

                    <!-- 键盘布局 -->
                    <div class="keyboard-container mb-3">
                        <div class="col-span-3 flex justify-center">
                            <button id="btn-up" class="key-button text-sm">W</button>
                        </div>
                        <div class="col-span-3 grid grid-cols-3 gap-2">
                            <div class="col-start-1 flex justify-end">
                                <button id="btn-left" class="key-button text-sm">A</button>
                            </div>
                            <div class="flex justify-center">
                                <button id="btn-down" class="key-button text-sm">S</button>
                            </div>
                            <div class="flex justify-start">
                                <button id="btn-right" class="key-button text-sm">D</button>
                            </div>
                        </div>
                    </div>

                    <div class="robot-arena">
                        <div id="robot" class="robot">
                            <i class="fa fa-arrow-up"></i>
                        </div>
                    </div>

                    <div class="mt-2 text-xs text-gray-500 flex flex-wrap gap-x-4">
                        <div class="w-full sm:w-auto"><span>当前指令:</span> <span id="current-command">等待输入...</span></div>
                        <div class="w-full sm:w-auto"><span>步态模式:</span> <span id="gait-mode">Triangle</span></div>
                    </div>
                </div>
                <div class="absolute -bottom-3 -right-3 w-12 h-12 bg-control/10 rounded-full"></div>
            </div>
        </div>

        <!-- 右侧区域 -->
        <div class="absolute right-0 top-0 bottom-0 w-1/2 grid grid-layout-right">
            <!-- 右侧上下分隔线 -->
            <div class="absolute left-0 right-0 top-1/2 h-[5px] bg-frame -mt-[2.5px] z-10"></div>

            <!-- 右上区域 - 六足机器人3D可视化 -->
            <div class="bg-white p-4 overflow-hidden relative">
                <div class="absolute inset-0 bg-accent/5 z-0"></div>
                <div class="relative z-10">
                    <h2 class="text-lg font-bold text-dark mb-2 flex items-center">
                        <i class="fa fa-cogs text-accent mr-2"></i>
                        机器人3D可视化
                    </h2>

                    <!-- 3D可视化容器 -->
                    <div class="robot-visualization" id="robot-3d-container"></div>
                </div>
                <div class="absolute -top-3 -right-3 w-12 h-12 bg-accent/10 rounded-full"></div>
            </div>

            <!-- 右下区域 - 360雷达点云图 -->
            <div class="bg-white p-4 overflow-hidden relative">
                <div class="absolute inset-0 bg-dark/5 z-0"></div>
                <div class="relative z-10">
                    <h2 class="text-lg font-bold text-dark mb-2 flex items-center">
                        <i class="fa fa-rss text-dark mr-2"></i>
                        360°雷达点云图
                    </h2>

                    <div class="radar-container" id="radar-container">
                        <!-- 雷达控制面板 -->
                        <div class="radar-controls">
                            <button id="toggle-radar" class="radar-control-btn">
                                <i class="fa fa-pause"></i>
                            </button>
                            <button id="zoom-radar-in" class="radar-control-btn">
                                <i class="fa fa-search-plus"></i>
                            </button>
                            <button id="zoom-radar-out" class="radar-control-btn">
                                <i class="fa fa-search-minus"></i>
                            </button>
                        </div>

                        <!-- 雷达Canvas -->
                        <canvas id="radar-canvas" width="400" height="300"></canvas>

                        <!-- 雷达状态 -->
                        <div class="absolute bottom-2 left-2 text-xs text-white/80">
                            <span id="radar-status">状态: 正在扫描...</span>
                        </div>
                    </div>
                </div>
                <div class="absolute -bottom-3 -left-3 w-12 h-12 bg-dark/10 rounded-full"></div>
            </div>
        </div>
    </div>

    <script>
        // 全局数据结构
        const esp32Data = {
            videoStream: null,
            radarPoints: [],
            robotStatus: {
                position: { x: 50, y: 50 },
                direction: 0,
                gait: 'triangle'
            }
        };

        // DOM加载完成后初始化所有功能
        document.addEventListener('DOMContentLoaded', () => {
            // 初始化视频流
            initVideoStream();

            // 初始化机器人控制（包含按键反馈）
            initRobotControl();

            // 初始化3D可视化
            initRobot3DVisualization();

            // 初始化雷达点云图
            initRadar();

            // 模拟从ESP32接收数据
            simulateESP32Data();
        });

        // ====================== 视频流处理 ======================
        function initVideoStream() {
            const videoElement = document.getElementById('esp32-cam-video');
            const videoPlaceholder = document.getElementById('video-placeholder');
            const refreshButton = document.getElementById('refresh-video');
            const fullscreenButton = document.getElementById('fullscreen-video');

            // 模拟视频加载
            setTimeout(() => {
                videoPlaceholder.classList.add('hidden');
                videoElement.classList.remove('hidden');
            }, 1500);

            // 刷新视频
            refreshButton.addEventListener('click', () => {
                videoElement.classList.add('hidden');
                videoPlaceholder.classList.remove('hidden');
                setTimeout(() => {
                    videoPlaceholder.classList.add('hidden');
                    videoElement.classList.remove('hidden');
                }, 1000);
            });

            // 全屏显示视频
            fullscreenButton.addEventListener('click', () => {
                const videoContainer = document.querySelector('.video-container');
                if (videoContainer.requestFullscreen) {
                    videoContainer.requestFullscreen();
                } else if (videoContainer.webkitRequestFullscreen) { /* Safari */
                    videoContainer.webkitRequestFullscreen();
                } else if (videoContainer.msRequestFullscreen) { /* IE11 */
                    videoContainer.msRequestFullscreen();
                }
            });
        }

        // ====================== 机器人控制 ======================
        function initRobotControl() {
            const robot = {
                element: document.getElementById('robot'),
                commandDisplay: document.getElementById('current-command'),
                gaitDisplay: document.getElementById('gait-mode'),
                updateDisplay() {
                    this.element.style.left = `${esp32Data.robotStatus.position.x}%`;
                    this.element.style.top = `${esp32Data.robotStatus.position.y}%`;
                    this.element.style.transform = `rotate(${esp32Data.robotStatus.direction * 90}deg)`;
                    this.gaitDisplay.textContent = esp32Data.robotStatus.gait.charAt(0).toUpperCase() + esp32Data.robotStatus.gait.slice(1);
                }
            };

            // 按键映射
            const keyMappings = {
                'w': 'btn-up',
                's': 'btn-down',
                'a': 'btn-left',
                'd': 'btn-right'
            };

            // 移动机器人
            function moveRobot(direction) {
                const speed = 5;
                const arena = document.querySelector('.robot-arena');
                const arenaRect = arena.getBoundingClientRect();
                const robotSize = robot.element.offsetWidth;
                const maxX = 100 - (robotSize / arenaRect.width * 100);
                const maxY = 100 - (robotSize / arenaRect.height * 100);

                const prevX = esp32Data.robotStatus.position.x;
                const prevY = esp32Data.robotStatus.position.y;

                switch(direction) {
                    case 'up':
                        esp32Data.robotStatus.position.y = Math.max(0, prevY - speed);
                        esp32Data.robotStatus.direction = 0;
                        break;
                    case 'down':
                        esp32Data.robotStatus.position.y = Math.min(maxY, prevY + speed);
                        esp32Data.robotStatus.direction = 2;
                        break;
                    case 'left':
                        esp32Data.robotStatus.position.x = Math.max(0, prevX - speed);
                        esp32Data.robotStatus.direction = 3;
                        break;
                    case 'right':
                        esp32Data.robotStatus.position.x = Math.min(maxX, prevX + speed);
                        esp32Data.robotStatus.direction = 1;
                        break;
                }

                // 更新显示
                robot.updateDisplay();

                // 显示当前指令
                robot.commandDisplay.textContent = direction;

                // 更新3D模型姿态
                updateRobot3DPosition(
                    esp32Data.robotStatus.position.x,
                    esp32Data.robotStatus.position.y,
                    esp32Data.robotStatus.direction
                );

                // 更新雷达中心点
                updateRadarCenter(
                    esp32Data.robotStatus.position.x,
                    esp32Data.robotStatus.position.y
                );

                // 模拟发送指令到ESP32
                sendCommandToESP32({
                    type: 'move',
                    direction: direction
                });
            }

            // 步态切换
            function switchGait(gaitType) {
                const gaitButtons = document.querySelectorAll('#gait-wave, #gait-triangle');
                gaitButtons.forEach(button => {
                    button.classList.remove('bg-control', 'text-white');
                    button.classList.add('bg-gray-200', 'text-gray-700');
                });

                const activeButton = document.getElementById(`gait-${gaitType}`);
                if (activeButton) {
                    activeButton.classList.remove('bg-gray-200', 'text-gray-700');
                    activeButton.classList.add('bg-control', 'text-white');
                }

                esp32Data.robotStatus.gait = gaitType;
                robot.updateDisplay();

                // 更新3D模型步态
                updateRobot3DGait(gaitType);

                // 模拟发送指令到ESP32
                sendCommandToESP32({
                    type: 'gait',
                    gait: gaitType
                });
            }

            // 高亮按键
            function highlightKey(key) {
                const btnId = keyMappings[key.toLowerCase()];
                if (btnId) {
                    const btn = document.getElementById(btnId);
                    btn.classList.add('key-button-active');
                }
            }

            // 取消高亮按键
            function unhighlightKey(key) {
                const btnId = keyMappings[key.toLowerCase()];
                if (btnId) {
                    const btn = document.getElementById(btnId);
                    btn.classList.remove('key-button-active');
                }
            }

            // 绑定按键事件
            document.getElementById('btn-up').addEventListener('mousedown', () => {
                highlightKey('w');
                moveRobot('up');
            });
            document.getElementById('btn-down').addEventListener('mousedown', () => {
                highlightKey('s');
                moveRobot('down');
            });
            document.getElementById('btn-left').addEventListener('mousedown', () => {
                highlightKey('a');
                moveRobot('left');
            });
            document.getElementById('btn-right').addEventListener('mousedown', () => {
                highlightKey('d');
                moveRobot('right');
            });

            // 鼠标释放事件
            document.addEventListener('mouseup', () => {
                Object.keys(keyMappings).forEach(key => unhighlightKey(key));
            });

            // 键盘控制
            document.addEventListener('keydown', (e) => {
                const key = e.key.toLowerCase();
                if (keyMappings[key]) {
                    e.preventDefault(); // 防止页面滚动
                    highlightKey(key);
                    moveRobot(key === 'w' ? 'up' : key === 's' ? 'down' : key === 'a' ? 'left' : 'right');
                }
            });

            // 键盘释放事件
            document.addEventListener('keyup', (e) => {
                const key = e.key.toLowerCase();
                if (keyMappings[key]) {
                    unhighlightKey(key);
                }
            });

            // 绑定步态切换事件
            document.getElementById('gait-wave').addEventListener('click', () => switchGait('wave'));
            document.getElementById('gait-triangle').addEventListener('click', () => switchGait('triangle'));

            // 初始化机器人显示
            robot.updateDisplay();
        }

        // ====================== 3D可视化逻辑 ======================
        let scene, camera, renderer, controls;
        let robotModel, robotBase;
        let legs = [];
        let animationPhase = 0;

        // 初始化3D可视化
        function initRobot3DVisualization() {
            const container = document.getElementById('robot-3d-container');
            const width = container.clientWidth;
            const height = container.clientHeight;

            // 创建场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xf0f0f0);

            // 创建相机
            camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
            camera.position.z = 20;
            camera.position.y = 15;
            camera.lookAt(0, 0, 0);

            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(width, height);
            container.appendChild(renderer.domElement);

            // 添加轨道控制器
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.25;
            controls.enableZoom = true;

            // 添加光源
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
            scene.add(ambientLight);

            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight.position.set(1, 1, 1);
            scene.add(directionalLight);

            // 创建地面
            const planeGeometry = new THREE.PlaneGeometry(100, 100);
            const planeMaterial = new THREE.MeshBasicMaterial({ color: 0xe0e0e0, side: THREE.DoubleSide });
            const plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.rotation.x = Math.PI / 2;
            plane.position.y = -1;
            scene.add(plane);

            // 创建网格辅助线
            const gridHelper = new THREE.GridHelper(100, 100, 0xcccccc, 0xcccccc);
            scene.add(gridHelper);

            // 创建六足机器人模型
            createRobotModel();

            // 开始动画循环
            animate();

            // 窗口大小变化时调整渲染器
            window.addEventListener('resize', () => {
                const newWidth = container.clientWidth;
                const newHeight = container.clientHeight;
                camera.aspect = newWidth / newHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(newWidth, newHeight);
            });
        }

        // 创建六足机器人模型
        function createRobotModel() {
            // 创建机器人基座
            const baseGeometry = new THREE.BoxGeometry(6, 1, 4);
            const baseMaterial = new THREE.MeshStandardMaterial({ color: 0x40a9ff });
            robotBase = new THREE.Mesh(baseGeometry, baseMaterial);
            scene.add(robotBase);

            // 创建六条腿
            const legPositions = [
                // 左前
                { x: -3, z: 2, startAngle: 0 },
                // 左中
                { x: -3, z: 0, startAngle: 0 },
                // 左后
                { x: -3, z: -2, startAngle: 0 },
                // 右前
                { x: 3, z: 2, startAngle: Math.PI },
                // 右中
                { x: 3, z: 0, startAngle: Math.PI },
                // 右后
                { x: 3, z: -2, startAngle: Math.PI }
            ];

            legPositions.forEach((position, index) => {
                const leg = createLeg(position.x, position.z, position.startAngle);
                legs.push(leg);
                robotBase.add(leg);
            });

            // 创建机器人整体组
            robotModel = new THREE.Group();
            robotModel.add(robotBase);
            scene.add(robotModel);
        }

        // 创建单条腿
        function createLeg(x, z, startAngle) {
            const legGroup = new THREE.Group();
            legGroup.position.set(x, 0, z);
            legGroup.rotation.y = startAngle;

            // 腿节1（髋关节）
            const hipGeometry = new THREE.BoxGeometry(0.8, 0.8, 2);
            const hipMaterial = new THREE.MeshStandardMaterial({ color: 0xff7d00 });
            const hip = new THREE.Mesh(hipGeometry, hipMaterial);
            hip.position.z = 1;
            legGroup.add(hip);

            // 腿节2（膝关节）
            const kneeGeometry = new THREE.BoxGeometry(0.6, 0.6, 3);
            const kneeMaterial = new THREE.MeshStandardMaterial({ color: 0xff7d00 });
            const knee = new THREE.Mesh(kneeGeometry, kneeMaterial);
            knee.position.z = 3.5;
            legGroup.add(knee);

            // 腿节3（踝关节/足部）
            const ankleGeometry = new THREE.BoxGeometry(0.5, 0.5, 3);
            const ankleMaterial = new THREE.MeshStandardMaterial({ color: 0xff4d00 });
            const ankle = new THREE.Mesh(ankleGeometry, ankleMaterial);
            ankle.position.z = 6.5;
            legGroup.add(ankle);

            // 足部
            const footGeometry = new THREE.SphereGeometry(0.5);
            const footMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });
            const foot = new THREE.Mesh(footGeometry, footMaterial);
            foot.position.z = 8;
            legGroup.add(foot);

            // 存储关节引用，便于动画控制
            legGroup.joints = {
                hip: hip,
                knee: knee,
                ankle: ankle,
                foot: foot
            };

            return legGroup;
        }

        // 更新机器人3D模型位置
        function updateRobot3DPosition(x, y, direction) {
            // 转换为3D坐标
            const posX = (x - 50) / 5;
            const posZ = (y - 50) / 5;

            robotModel.position.x = posX;
            robotModel.position.z = posZ;
            robotModel.rotation.y = direction * Math.PI / 2;
        }

        // 更新机器人3D模型步态
        function updateRobot3DGait(newGaitType) {
            esp32Data.robotStatus.gait = newGaitType;
            animationPhase = 0; // 重置动画阶段
        }

        // 动画循环
        function animate() {
            requestAnimationFrame(animate);

            // 更新动画阶段
            animationPhase += 0.05;

            // 根据步态类型更新腿部动画
            updateLegAnimation();

            controls.update();
            renderer.render(scene, camera);
        }

        // 更新腿部动画
        function updateLegAnimation() {
            // 根据步态类型计算腿部位置
            legs.forEach((leg, index) => {
                // 计算当前腿的相位偏移
                let phaseOffset = 0;

                if (esp32Data.robotStatus.gait === 'wave') {
                    // Wave步态：依次移动每条腿
                    phaseOffset = (index * Math.PI / 3);
                } else if (esp32Data.robotStatus.gait === 'triangle') {
                    // Triangle步态：交替移动两组腿
                    const group = index < 3 ? 0 : 1;
                    phaseOffset = group * Math.PI;
                }

                // 计算当前腿的动画相位
                const legPhase = animationPhase + phaseOffset;

                // 计算抬腿高度（使用正弦函数创建波浪效果）
                const liftHeight = Math.max(0, Math.sin(legPhase));

                // 更新腿部关节角度
                const joints = leg.joints;

                // 髋关节上下摆动
                joints.hip.rotation.x = Math.sin(legPhase) * 0.3;

                // 膝关节弯曲
                joints.knee.rotation.x = -Math.sin(legPhase) * 0.5 - 0.5;

                // 踝关节调整
                joints.ankle.rotation.x = Math.sin(legPhase) * 0.2 + 0.3;

                // 足部位置调整（模拟行走）
                const walkCycle = Math.sin(legPhase + Math.PI);
                joints.foot.position.z = 8 + walkCycle * 1.5;
                joints.foot.position.y = liftHeight * 1.5;
            });
        }

        // ====================== 雷达点云图逻辑 ======================
        let radarCanvas, radarCtx;
        let radarRotation = 0;
        let radarRunning = true;
        let radarZoom = 1;
        let radarCenterX = 200;
        let radarCenterY = 150;
        let robotPositionInRadar = { x: 200, y: 150 };

        // 初始化雷达
        function initRadar() {
            radarCanvas = document.getElementById('radar-canvas');
            radarCtx = radarCanvas.getContext('2d');

            // 调整Canvas大小以匹配容器
            resizeRadarCanvas();
            window.addEventListener('resize', resizeRadarCanvas);

            // 绑定控制按钮
            document.getElementById('toggle-radar').addEventListener('click', toggleRadar);
            document.getElementById('zoom-radar-in').addEventListener('click', () => { radarZoom = Math.min(radarZoom * 1.2, 5); });
            document.getElementById('zoom-radar-out').addEventListener('click', () => { radarZoom = Math.max(radarZoom / 1.2, 0.5); });

            // 开始雷达扫描动画
            animateRadar();
        }

        // 调整雷达Canvas大小
        function resizeRadarCanvas() {
            const container = document.getElementById('radar-container');
            radarCanvas.width = container.clientWidth;
            radarCanvas.height = container.clientHeight;

            // 更新雷达中心点
            radarCenterX = radarCanvas.width / 2;
            radarCenterY = radarCanvas.height / 2;
            robotPositionInRadar = { x: radarCenterX, y: radarCenterY };
        }

        // 更新雷达中心点（跟随机器人位置）
        function updateRadarCenter(x, y) {
            // 转换为雷达坐标系
            const arenaWidth = document.querySelector('.robot-arena').clientWidth;
            const arenaHeight = document.querySelector('.robot-arena').clientHeight;

            const normalizedX = (x / 100) * arenaWidth;
            const normalizedY = (y / 100) * arenaHeight;

            // 映射到雷达中心
            robotPositionInRadar.x = radarCenterX + (normalizedX - arenaWidth/2) * 0.5;
            robotPositionInRadar.y = radarCenterY + (normalizedY - arenaHeight/2) * 0.5;
        }

        // 切换雷达运行状态
        function toggleRadar() {
            radarRunning = !radarRunning;
            const btn = document.getElementById('toggle-radar');
            btn.innerHTML = radarRunning ? '<i class="fa fa-pause"></i>' : '<i class="fa fa-play"></i>';
            document.getElementById('radar-status').textContent = `状态: ${radarRunning ? '正在扫描...' : '已暂停'}`;
        }

        // 雷达动画循环
        function animateRadar() {
            if (radarRunning) {
                // 清除画布
                radarCtx.clearRect(0, 0, radarCanvas.width, radarCanvas.height);

                // 绘制背景
                drawRadarBackground();

                // 绘制所有点
                drawRadarPoints();

                // 绘制雷达扫描线
                drawRadarScanLine();

                // 绘制机器人位置
                drawRobotPosition();

                // 更新雷达旋转角度
                radarRotation += 0.03;
                if (radarRotation > Math.PI * 2) {
                    radarRotation -= Math.PI * 2;
                }
            }

            requestAnimationFrame(animateRadar);
        }

        // 绘制雷达背景
        function drawRadarBackground() {
            // 绘制背景黑色
            radarCtx.fillStyle = '#000';
            radarCtx.fillRect(0, 0, radarCanvas.width, radarCanvas.height);

            // 绘制雷达圆圈
            radarCtx.strokeStyle = 'rgba(0, 255, 0, 0.2)';
            radarCtx.lineWidth = 1;

            // 绘制多个同心圆
            const maxRadius = Math.min(radarCanvas.width, radarCanvas.height) * 0.45;
            for (let i = 1; i <= 5; i++) {
                const radius = (maxRadius / 5) * i;
                radarCtx.beginPath();
                radarCtx.arc(radarCenterX, radarCenterY, radius / radarZoom, 0, Math.PI * 2);
                radarCtx.stroke();
            }

            // 绘制十字线
            radarCtx.beginPath();
            radarCtx.moveTo(radarCenterX - maxRadius / radarZoom, radarCenterY);
            radarCtx.lineTo(radarCenterX + maxRadius / radarZoom, radarCenterY);
            radarCtx.moveTo(radarCenterX, radarCenterY - maxRadius / radarZoom);
            radarCtx.lineTo(radarCenterX, radarCenterY + maxRadius / radarZoom);
            radarCtx.stroke();

            // 绘制距离标记
            radarCtx.fillStyle = 'rgba(0, 255, 0, 0.5)';
            radarCtx.font = '10px monospace';

            for (let i = 1; i <= 5; i++) {
                const radius = (maxRadius / 5) * i;
                const text = `${i * 50}cm`;
                const textWidth = radarCtx.measureText(text).width;

                radarCtx.fillText(text, radarCenterX + radius / radarZoom - textWidth - 5, radarCenterY - 5);
            }
        }

        // 绘制雷达点
        function drawRadarPoints() {
            esp32Data.radarPoints.forEach(point => {
                // 计算点在Canvas上的实际位置
                const x = radarCenterX + point.x / radarZoom;
                const y = radarCenterY + point.y / radarZoom;

                // 计算点与扫描线的角度差
                const pointAngle = Math.atan2(point.y, point.x);
                const angleDiff = Math.abs(pointAngle - radarRotation);

                // 如果点在当前扫描线上，增强显示
                let intensity = point.intensity;
                if (angleDiff < 0.1 || angleDiff > Math.PI * 2 - 0.1) {
                    intensity = 1;
                }

                // 根据强度决定点的颜色
                const alpha = 0.3 + intensity * 0.7;
                const green = Math.floor(100 + intensity * 155);

                // 绘制点
                radarCtx.fillStyle = `rgba(0, ${green}, 0, ${alpha})`;
                radarCtx.beginPath();
                radarCtx.arc(x, y, 2, 0, Math.PI * 2);
                radarCtx.fill();
            });
        }

        // 绘制雷达扫描线
        function drawRadarScanLine() {
            const maxRadius = Math.min(radarCanvas.width, radarCanvas.height) * 0.45;

            // 绘制扫描线
            radarCtx.strokeStyle = 'rgba(0, 255, 0, 0.3)';
            radarCtx.lineWidth = 1;
            radarCtx.beginPath();
            radarCtx.moveTo(radarCenterX, radarCenterY);
            radarCtx.lineTo(
                radarCenterX + Math.cos(radarRotation) * maxRadius / radarZoom,
                radarCenterY + Math.sin(radarRotation) * maxRadius / radarZoom
            );
            radarCtx.stroke();

            // 绘制扇形扫描区域
            const gradient = radarCtx.createRadialGradient(
                radarCenterX, radarCenterY, 0,
                radarCenterX, radarCenterY, maxRadius / radarZoom
            );

            gradient.addColorStop(0, 'rgba(0, 255, 0, 0.05)');
            gradient.addColorStop(1, 'rgba(0, 255, 0, 0)');

            radarCtx.fillStyle = gradient;
            radarCtx.beginPath();
            radarCtx.moveTo(radarCenterX, radarCenterY);
            radarCtx.arc(radarCenterX, radarCenterY, maxRadius / radarZoom, radarRotation - 0.3, radarRotation);
            radarCtx.closePath();
            radarCtx.fill();
        }

        // 绘制机器人位置
        function drawRobotPosition() {
            // 绘制机器人位置标记
            radarCtx.fillStyle = 'rgba(255, 0, 0, 0.8)';
            radarCtx.beginPath();
            radarCtx.arc(robotPositionInRadar.x, robotPositionInRadar.y, 5, 0, Math.PI * 2);
            radarCtx.fill();

            // 绘制方向指示
            const directionAngle = esp32Data.robotStatus.direction * Math.PI / 2;
            radarCtx.strokeStyle = 'rgba(255, 0, 0, 0.8)';
            radarCtx.lineWidth = 2;
            radarCtx.beginPath();
            radarCtx.moveTo(robotPositionInRadar.x, robotPositionInRadar.y);
            radarCtx.lineTo(
                robotPositionInRadar.x + Math.cos(directionAngle) * 15,
                robotPositionInRadar.y + Math.sin(directionAngle) * 15
            );
            radarCtx.stroke();
        }

        // ====================== 模拟ESP32数据 ======================
        function simulateESP32Data() {
            // 模拟雷达点云数据
            setInterval(() => {
                // 清除旧点
                if (esp32Data.radarPoints.length > 100) {
                    esp32Data.radarPoints = esp32Data.radarPoints.slice(-50);
                }

                // 添加新点
                for (let i = 0; i < 5; i++) {
                    const angle = Math.random() * Math.PI * 2;
                    const distance = Math.random() * 200 + 50;
                    const intensity = Math.random();

                    esp32Data.radarPoints.push({
                        x: Math.cos(angle) * distance,
                        y: Math.sin(angle) * distance,
                        intensity: intensity
                    });
                }
            }, 200);
        }

        // 模拟发送命令到ESP32
        function sendCommandToESP32(command) {
            console.log('发送命令到ESP32:', command);
            // 在实际应用中，这里应该通过WebSocket或其他通信方式发送命令到ESP32
        }
    </script>
</body>
</html>
